package controllers

import (
	"fmt"
	"net/http"
	"os"
	"strings"
	"time"
	models "yuanaiproblem/dao/model"
	response "yuanaiproblem/models"
	"yuanaiproblem/models/dto"
	"yuanaiproblem/pkg/aiserve"
	"yuanaiproblem/services"
	"yuanaiproblem/utils"

	"github.com/gin-gonic/gin"
)

// GenerateQuestion 生成题目接口（支持多AI模型选择）
// 入参：请求体（题目生成参数）、查询参数（ai_model，可选）
// 流程：验证当前用户 -> 解析并校验请求参数 -> 构建AI提示词 -> 选择AI服务 -> 生成题目 -> 临时缓存题目 -> 返回结果
func GenerateQuestion(c *gin.Context) {
	//获取当前登录用户
	currentUser, err := utils.GetCurrentUser(c)
	if err != nil {
		response.Error(c, http.StatusUnauthorized, err.Error())
		return
	}
	// 解析并验证请求参数（包含AI模型选择参数）
	var req dto.GenerateQuestionRequest
	if err := utils.BindAndValidate(c, &req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}
	// 判断语言是否由系统支持
	isContain, supportedLangs := utils.IsContainLanguage(req.Subject)
	if !isContain {
		supportedStr := strings.Join(supportedLangs, ", ")
		response.Error(c, http.StatusBadRequest, fmt.Sprintf("语言不支持,系统仅支持%s", supportedStr))
		return
	}
	//这里单独解析
	aiModel := c.DefaultQuery("ai_model", "doubao") // 默认为豆包
	// 构建AI提示词
	prompt := utils.BuildPromptFromDTO(req)
	// 根据请求参数选择对应的AI服务
	var myAiService aiserve.AIService
	switch aiModel {
	case "doubao":
		// 豆包配置：从环境变量读取所有参数
		config := aiserve.AIConfig{
			APIKey:      os.Getenv("DOUBAO_API_KEY"),
			BaseURL:     os.Getenv("DOUBAO_BASE_URL"),
			Model:       os.Getenv("DOUBAO_MODEL"),
			Temperature: float32(utils.GetEnvFloat("DOUBAO_TEMPERATURE", 0.7)), // 默认0.7
			MaxTokens:   utils.GetEnvInt("DOUBAO_MAX_TOKENS", 2000),            // 默认2000
			Timeout:     utils.GetEnvInt("DOUBAO_TIMEOUT", 30),                 // 默认30秒
		}
		// 豆包AI
		myAiService = aiserve.NewDoubaoAIService(config)
	case "tongyi":
		// 通义千问配置：从环境变量读取所有参数
		config := aiserve.AIConfig{
			APIKey:      os.Getenv("TONGYI_API_KEY"),
			BaseURL:     os.Getenv("TONGYI_BASE_URL"),
			Model:       os.Getenv("TONGYI_MODEL"),
			Temperature: float32(utils.GetEnvFloat("TONGYI_TEMPERATURE", 0.7)),
			MaxTokens:   utils.GetEnvInt("TONGYI_MAX_TOKENS", 2000),
			Timeout:     utils.GetEnvInt("TONGYI_TIMEOUT", 30),
		}
		//通义千问
		myAiService = aiserve.NewTongyiAIService(config)
	default:
		// 默认使用豆包AI
		myAiService = aiserve.NewDoubaoAIService(aiserve.AIConfig{APIKey: os.Getenv("DOUBAO_API_KEY")})
	}
	// 调用选中的AI服务生成题目
	questions, err := myAiService.GenerateQuestions(prompt, req.Count, currentUser.ID)
	fmt.Println(questions)

	//questions, err := myAiService.GenerateQuestions(prompt, req.Count, 123)
	if err != nil {
		utils.HandleAIError(c, err)
		return
	}
	// 临时缓存生成的题目
	//redisKey, err := utils.HandleTempQuestions(c, currentUser.ID, questions)
	redisKey, err := utils.HandleTempQuestions(c, currentUser.ID, questions)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "临时缓存题目失败: "+err.Error())
		return
	}
	// 返回生成题目的响应数据
	data := dto.GenerateQuestionResponse{
		AIModel:   aiModel,
		RedisKey:  redisKey,
		Questions: questions,
		ExpireAt:  time.Now().Add(30 * time.Minute).Format("2006-01-02 15:04:05"),
	}
	// 返回包含使用的AI模型信息的成功响应
	response.Success(c, data, "题目生成成功, 请在30分钟内完成编辑")
}

// SaveEditedQuestions 保存编辑后的题目入库
// 入参：请求体（临时ID、编辑后的题目列表）
// 流程：验证当前用户 -> 解析并校验请求参数 -> 调用服务层保存题目 -> 返回结果
func SaveEditedQuestions(c *gin.Context) {
	// 获取当前登录用户
	currentUser, err := utils.GetCurrentUser(c)
	if err != nil {
		response.Error(c, http.StatusUnauthorized, err.Error())
		return
	}
	// 解析并验证请求参数
	var req dto.SaveQuestionsRequest
	if err := utils.BindAndValidate(c, &req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 调用服务层保存题目
	err = services.SaveQuestions(
		currentUser,
		req.TempID,
		req.Questions,
	)
	if err != nil {
		utils.HandleQuestionServiceError(c, err)
		return
	}
	// 返回成功响应
	response.Success(c, nil, "题目已成功入库")
}

// GetUserQuestions 获取用户名下所有已入库的题目
// 入参：查询参数（page、page_size）
// 流程：验证当前用户 -> 解析分页参数 -> 调用服务层查询题目 -> 返回分页结果
func GetUserQuestions(c *gin.Context) {
	fmt.Println("查询用户题目列表")
	// 1. 获取当前登录用户
	currentUser, err := utils.GetCurrentUser(c)
	if err != nil {
		response.Error(c, http.StatusUnauthorized, err.Error())
		return
	}
	// 解析分页参数
	var params struct {
		Page     int `form:"page" default:"1"`
		PageSize int `form:"page_size" default:"20"`
	}
	if err := c.ShouldBindQuery(&params); err != nil {
		response.Error(c, http.StatusBadRequest, "参数解析失败: "+err.Error())
		return
	}
	// 调用服务层查询题目
	result, err := services.GetUserQuestions(
		currentUser.ID,
		params.Page,
		params.PageSize,
	)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "查询题目失败: "+err.Error())
		return
	}
	// 返回成功响应
	response.Success(c, gin.H{
		"count":     result.Count,
		"list":      result.List,
		"page":      params.Page,
		"page_size": params.PageSize,
	}, "查询成功")
}

// UpdateQuestion 更新题目
// 入参：路径参数（id）、请求体（待更新的题目信息）
// 流程：验证当前用户 -> 解析题目ID -> 解析并校验请求参数 -> 调用服务层更新题目 -> 返回结果
func UpdateQuestion(c *gin.Context) {
	// 获取当前登录用户
	currentUser, err := utils.GetCurrentUser(c)
	if err != nil {
		response.Error(c, http.StatusUnauthorized, err.Error())
		return
	}
	// 解析题目ID
	questionID, err := utils.ParseParamToUint(c, "id")
	if err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}
	// 解析并验证请求参数
	var req dto.UpdateQuestionRequest
	if err := utils.BindAndValidate(c, &req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数格式错误: "+err.Error())
		return
	}
	// 调用服务层更新题目
	updatedQuestion, err := services.UpdateQuestion(
		currentUser.ID,
		currentUser.Role == models.RoleAdmin,
		questionID,
		req.Title,
		req.QuestionType,
		req.Options,
		req.Answer,
		req.Explanation,
		req.Keywords,
		req.Language,
	)
	if err != nil {
		utils.HandleQuestionServiceError(c, err)
		return
	}
	// 返回成功响应
	response.Success(c, gin.H{"question": updatedQuestion}, "题目已更新")
}

// DeleteQuestion 软删除题目
// 入参：路径参数（id）
// 流程：验证当前用户 -> 解析题目ID -> 判断用户权限 -> 调用服务层软删除题目 -> 返回结果
func DeleteQuestion(c *gin.Context) {
	fmt.Println("执行删除题目")
	// 获取当前登录用户
	currentUser, err := utils.GetCurrentUser(c)
	if err != nil {
		response.Error(c, http.StatusUnauthorized, err.Error())
		return
	}
	// 解析题目ID
	questionID, err := utils.ParseParamToUint(c, "id")
	if err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}
	// 判断是否为管理员
	isAdmin := currentUser.Role == models.RoleAdmin
	// 调用服务层删除题目
	deletedAt, err := services.DeleteQuestion(
		currentUser.ID,
		isAdmin,
		questionID,
	)
	if err != nil {
		utils.HandleQuestionServiceError(c, err)
		return
	}
	// 返回成功响应
	response.Success(c, gin.H{"deleted_at": deletedAt}, "题目已删除")
}

// GetSupportLanguage 获取系统支持的编程语言-只有controller层
// 入参：context
// 返回：系统支持的语言（从环境变量读取，自动去重、去空，无配置时返回默认值）
func GetSupportLanguage(c *gin.Context) {
	// 从环境变量读取配置，无配置时使用默认值
	langStr := os.Getenv("SUPPORTED_LANGUAGES")
	if langStr == "" {
		langStr = "go,python" // 默认支持的语言
	}
	// 解析并处理语言列表（去重、去空）
	langSet := make(map[string]struct{})
	for _, lang := range strings.Split(langStr, ",") {
		lang = strings.TrimSpace(lang) // 去除前后空格
		if lang != "" {
			langSet[lang] = struct{}{} // 利用map去重
		}
	}
	// 转换为切片
	supportedLanguages := make([]string, 0, len(langSet))
	for lang := range langSet {
		supportedLanguages = append(supportedLanguages, lang)
	}

	// 返回结果
	response.Success(c, supportedLanguages, "获取系统支持的编程语言成功")
}
